package com.song.NettyTest;

import com.song.NacosServiceRegistry.ConsistentHashLoaderBalancer;
import com.song.NacosServiceRegistry.LoadBalancer;
import com.song.NacosServiceRegistry.RoundRobinLoadBalancer;
import com.song.Utils.ThreadPoolFactory;
import com.song.api.ByeService;
import com.song.api.HelloService;
import com.song.client.NettyClient;
import com.song.api.HelloObject;
import com.song.proxy.RPCClientProxy;
import com.song.transport.KryoSerializer;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.*;

@Slf4j(topic = "c.NettyClient")
public class NettyTestClient {
    public static void main(String[] args) {
        /**
         * 通过注册中心发现该服务的地址和端口
         * 因此构造 RpcClient 时不再需要传入地址和端口。
         */
//        LoadBalancer loadBalancer = new RandomLoadBalancer();
//        LoadBalancer loadBalancer = new RoundRobinLoadBalancer();//客户端选择采用哪种均衡机制
        LoadBalancer loadBalancer = new ConsistentHashLoaderBalancer();//客户端选择采用哪种均衡机制
        NettyClient client = new NettyClient(loadBalancer);
        client.setSerializer(new KryoSerializer());

        /**
         * 代理类使得我们只需要关心接口输入的信息HelloService  输入参数args  和  返回结果输出的信息   return 的结果
         * 其中的数据处理过程 和 其它功能不需要用户关心
         */
        //  JDK动态代理只能通过接口获取动态代理  rpcClientProxy作为代理所有细节对client隐藏真实实现，由代理来负责client所有请求
        RPCClientProxy rpcClientProxy = new RPCClientProxy(client);//rpcClientProxy对NettyClient 进行代理

        HelloService helloService = rpcClientProxy.getProxy(HelloService.class);// 结果返回给通用接口这个类

        HelloObject object = new HelloObject(13, "This client 1");//可序列化的消息类   这个需要通过通用接口发送至服务端
        String res = helloService.hello(object);
        System.out.println(res);

        ByeService byeService = rpcClientProxy.getProxy(ByeService.class);
        System.out.println(byeService.bye("NettyService"));

        //模拟多个用户同时向服务端发送消息
        ExecutorService pools = ThreadPoolFactory.createDefaultThreadPool("clientMSG", true);
        for(int i = 0;i < 10;++i) {
            int id = i;
            pools.submit(() -> {
                HelloObject obj = new HelloObject(id, "this is client" + id);
                String s = helloService.hello(obj);
                log.info("客户{}收到消息:{}", id, s);
                log.info(byeService.bye("NettyService, from Client " + id));
            });
        }
        pools.shutdown();
    }
}
